package com.gwtprocessingjs.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;

/**
 * This class demonstrates pulling data into Processing Javascript
 * code from GWT.
 */
public class JsFromGwt implements EntryPoint {
	
	// UI Elements.
	private final FlowPanel back = new FlowPanel();
	private final Label velocityHeader = new Label("Velocity: ");
	
	// Note that this TextBox is static, to go along with the static method 
	// that pulls its data.
	private static final TextBox velocityBox = new TextBox();
	
	@Override
	public void onModuleLoad() {
		
		// Note: methods used by the Javascript must be exported
		// before the canvas is initialized or the processing rendering
		// loop may crash as it attempts to access missing methods.
		exportUpdatePositionMethod();
		initializeCanvas();
		
		back.add(new Label("Pulling data from GWT into processing JS"));	
		HorizontalPanel hp = new HorizontalPanel();
		hp.add(velocityHeader);
		hp.add(velocityBox);
		velocityBox.setText("1");
		back.add(hp);
		RootPanel.get("gwt").add(back);
	}
	
	/**
	 * This method will get exported to a variable name that can be
	 * accessed from the JS file.
	 */
	public static int getVelocity() {
		try {
			int v = Integer.parseInt(velocityBox.getText());
			return Math.max(0, v);
		} catch (NumberFormatException e) {
			velocityBox.setText("1");
			return 1;
		}
	}
	
	// --- Private Methods ---
	
	/**
	 * Create an instance of Processing and associated it with the canvas
	 * element specified in the HTML file.
	 */
	private native void initializeCanvas() /*-{
		$wnd.initializeCanvas();
	}-*/;
	
	/**
	 * Calling GWT methods from straight JS requires special syntax and handling by the
	 * GWT compiler. Since the Javascript code is in an external JS file, GWT can't
	 * generate the glue, so the way to make those calls is by statically exporting
	 * the function name to a variable which can be accessed in the JS. For a better
	 * explanation see:
	 *
	 * <p>http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html
	 */
	private native void exportUpdatePositionMethod() /*-{
		
		// Bind the static updatePosition method on this class to
		// a variable in $wnd named "getVelocity"
		$wnd.getVelocity =
          $entry(@com.gwtprocessingjs.client.JsFromGwt::getVelocity());
	}-*/;
}
